package de.hauschild.gmltracer.tracer.impl.tier1;

import java.util.Collections;

import org.apache.commons.math.geometry.Vector3D;

import de.hauschild.gmltracer.tracer.Intersection;
import de.hauschild.gmltracer.tracer.Light;
import de.hauschild.gmltracer.tracer.Ray;
import de.hauschild.gmltracer.tracer.Shape;
import de.hauschild.gmltracer.tracer.impl.Vector3DUtils;

/**
 * The implementation of {@link Light} representing a simple directional light.
 * 
 * @author Klaus Hauschild
 * @since 1.0.0
 */
public class DirectionalLight implements Light {

  private final Vector3D direction;
  private final Vector3D color;

  /**
   * Instantiates a new directional light.
   * 
   * @param theDirection
   *          the direction
   * @param theColor
   *          the color
   */
  public DirectionalLight(final Vector3D theDirection, final Vector3D theColor) {
    direction = theDirection;
    color = theColor;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Vector3D getDirection() {
    return direction;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Vector3D illuminates(final Vector3D surfaceColor, final Intersection intersection) {
    final double dotProduct = Vector3D.dotProduct(intersection.getNormal(), direction.negate());
    final double lightIntensity = Math.max(0.0, dotProduct);

    return Vector3DUtils.multiplyComponentwise(surfaceColor, color).scalarMultiply(lightIntensity);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isInShadow(final Shape scene, final Intersection intersection) {
    final Ray shadowRay = new Ray(intersection.getPoint(), intersection.getPoint().add(getDirection().negate()));
    final Intersection shadowIntersection = scene.intersect(shadowRay, Collections.singletonList(intersection
        .getShape()));

    return shadowIntersection != null;
  }
}
